home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / networking / amitcp / httpd.lha / httpd / httpd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-18  |  6.7 KB  |  299 lines

  1. /*
  2.  * httpd.c: simple http daemon for answering WWW file requests
  3.  *
  4.  * 
  5.  * Rob McCool 3/21/93
  6.  * 
  7.  */
  8.  
  9.  
  10. #include "httpd.h"
  11.  
  12. #ifdef AMIGA
  13. long __near __stack = 80000;
  14. #endif
  15.  
  16. void usage(char *bin) {
  17.     fprintf(stderr,"Usage: %s [-d directory] [-f file] [-v]\n",bin);
  18.     fprintf(stderr,"-d directory : specify an alternate initial ServerRoot\n");
  19.     fprintf(stderr,"-f file : specify an alternate ServerConfigFile\n");
  20.     exit(1);
  21. }
  22.  
  23. int sd;
  24. pid_t pgrp;
  25.  
  26. #ifndef AMIGA
  27.  
  28. void detach() {
  29.     int x;
  30.  
  31.     chdir("/");
  32.     if((x = fork()) > 0)
  33.         exit(0);
  34.     else if(x == -1) {
  35.         fprintf(stderr,"httpd: unable to fork new process\n");
  36.         perror("fork");
  37.         exit(1);
  38.     }
  39. #ifndef NO_SETSID
  40.     if((pgrp=setsid()) == -1) {
  41.         fprintf(stderr,"httpd: setsid failed\n");
  42.         perror("setsid");
  43.         exit(1);
  44.     }
  45. #else
  46.     if((pgrp=setpgrp(getpid(),0)) == -1) {
  47.         fprintf(stderr,"httpd: setpgrp failed\n");
  48.         perror("setpgrp");
  49.         exit(1);
  50.     }
  51. #endif    
  52. }
  53.  
  54. void sig_term() {
  55.     log_error("httpd: caught SIGTERM, shutting down");
  56. #ifndef NO_KILLPG
  57.     killpg(pgrp,SIGKILL);
  58. #else
  59.     kill(-pgrp,SIGKILL);
  60. #endif
  61.     shutdown(sd,2);
  62.     close(sd);
  63. }
  64.  
  65. #ifndef AMIGA
  66. #ifdef BSD
  67. void ign() {
  68. #ifndef NEXT
  69.     int status;
  70. #else
  71.     union wait status;
  72. #endif
  73.     pid_t pid;
  74.  
  75.     while( (pid = wait3(&status, WNOHANG, NULL)) > 0);
  76. }
  77. #endif
  78. #endif
  79.  
  80. void bus_error() {
  81.     log_error("httpd: caught SIGBUS, dumping core");
  82.     chdir(server_root);
  83.     abort();         
  84. }
  85.  
  86. void seg_fault() {
  87.     log_error("httpd: caught SIGSEGV, dumping core");
  88.     chdir(server_root);
  89.     abort();
  90. }
  91.  
  92. void set_signals();
  93.  
  94. void restart() {
  95.     log_error("httpd: caught SIGHUP, restarting");
  96.     close_logs();
  97.     kill_mime();
  98.     kill_security();
  99.     if(server_hostname) {
  100.         free(server_hostname);
  101.         server_hostname = NULL;
  102.     }
  103.     read_config();
  104.     log_error("httpd: successful restart");
  105.     open_logs();
  106.     get_local_host();
  107.     set_signals();
  108. }
  109.  
  110. void set_signals() {
  111. #ifndef AMIGA
  112.     signal(SIGSEGV,(void (*)())seg_fault);
  113.     signal(SIGBUS,(void (*)())bus_error);
  114. #endif
  115.     signal(SIGTERM,(void (*)())sig_term);
  116. #ifndef AMIGA
  117.     signal(SIGHUP,(void (*)())restart);
  118.  
  119. #ifdef BSD
  120.     signal(SIGCHLD,(void (*)())ign);
  121. #else
  122.     signal(SIGCHLD,SIG_IGN);
  123. #endif
  124. #endif
  125. }
  126. #endif
  127.  
  128. #ifndef AMIGA
  129.  
  130. void standalone_main() {
  131.     int csd, clen,pid, one=1;
  132. #ifdef NEXT
  133.     struct sockaddr_in sa_server;
  134.     struct sockaddr sa_client;
  135. #else
  136.     struct sockaddr_in sa_server,sa_client;
  137. #endif
  138.  
  139.     detach();
  140.  
  141.     if ((sd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1) {
  142.         fprintf(stderr,"httpd: could not get socket\n");
  143.         perror("socket");
  144.         exit(1);
  145.     }
  146.  
  147.     if((setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,&one,sizeof(one))) == -1) {
  148.         fprintf(stderr,"httpd: could not set socket option\n");
  149.         perror("setsockopt");
  150.         exit(1);
  151.     }
  152.     bzero((char *) &sa_server, sizeof(sa_server));
  153.     sa_server.sin_family=AF_INET;
  154.     sa_server.sin_addr.s_addr=htonl(INADDR_ANY);
  155.     sa_server.sin_port=htons(port);
  156.     if(bind(sd,(struct sockaddr *) &sa_server,sizeof(sa_server)) == -1) {
  157.         fprintf(stderr,"httpd: could not bind to port %d\n",port);
  158.         perror("bind");
  159.         exit(1);
  160.     }
  161.     listen(sd,5);
  162.  
  163.     set_signals();
  164.     log_pid();
  165.  
  166.     while(1) {
  167.       retry:
  168.         clen=sizeof(sa_client);
  169.         if((csd=accept(sd,&sa_client,&clen)) == -1) {
  170.             if(errno == EINTR)  {
  171. #ifdef BSD
  172.                 ign();
  173. #endif
  174.                 goto retry;
  175.             }
  176.             log_error("socket error: accept failed");
  177.         }
  178.     /* we do this here so that logs can be opened as root */
  179.         if((pid = fork()) == -1)
  180.             log_error("unable to fork new process");
  181.         else if(!pid) {
  182.         struct passwd* pwent;
  183.             struct linger sl;
  184.  
  185.             sl.l_onoff = 1;
  186.             sl.l_linger = 600; /* currently ignored anyway */
  187.             /* this should check error status, but it's not crucial */
  188.             setsockopt(csd,SOL_SOCKET,SO_LINGER,&sl,sizeof(sl));
  189.  
  190.             close(0);
  191.             close(1);
  192.             dup2(csd,0);
  193.             dup2(csd,1);
  194.             close(sd);
  195.             /* Only try to switch if we're running as root */
  196.             if(!getuid()) {
  197.                 /* Now, make absolutely certain we don't have any privileges
  198.                  * except those mentioned in the configuration file. */
  199.                 if ((pwent = getpwuid(user_id)) == NULL)
  200.                     die(SERVER_ERROR,"couldn't determine user name from uid",
  201.                         stdout);
  202.                 /* Reset `groups' attribute. */
  203.                 if (initgroups(pwent->pw_name, group_id) == -1)
  204.                     die(SERVER_ERROR,"unable to setgroups",stdout);
  205.  
  206.                 /* Note the order, first setgid() and then setuid(), it
  207.                  * wouldn't work the other way around. */
  208.                 if (setgid(group_id) == -1)
  209.                     die(SERVER_ERROR,"unable to change gid",stdout);
  210.                 if (setuid(user_id) == -1)
  211.                     die(SERVER_ERROR,"unable to change uid",stdout);
  212.             }
  213.             process_request(0,stdout);
  214.             fclose(stdin);
  215.             fclose(stdout);
  216.             shutdown(csd,2);
  217.             close(csd);
  218.             exit(0);
  219.         }
  220.         close(csd);
  221.     }
  222. }
  223.  
  224. #endif
  225.  
  226. extern char *optarg;
  227. extern int optind;
  228.  
  229. main(int argc, char *argv[])
  230. {
  231.     int c;
  232. #ifdef AMITCP
  233.     int s = server_socket;
  234. #endif
  235.  
  236.     strcpy(server_root,HTTPD_ROOT);
  237.     make_full_path(server_root,SERVER_CONFIG_FILE,server_confname);
  238.  
  239.     while((c = getopt(argc,argv,"d:f:v")) != -1) {
  240.         switch(c) {
  241.           case 'd':
  242.             strcpy(server_root,optarg);
  243.       make_full_path(server_root,SERVER_CONFIG_FILE,server_confname);
  244.             break;
  245.           case 'f':
  246.             strcpy(server_confname,optarg);
  247.             break;
  248.           case 'v':
  249.             printf("NCSA httpd version %s.\n",SERVER_VERSION);
  250.             exit(1);
  251.           case '?':
  252.             usage(argv[0]);
  253.         }
  254.     }
  255.     read_config();
  256.     open_logs();
  257.     get_local_host();
  258.  
  259. #ifndef AMITCP
  260.  
  261.     if(standalone)
  262.         standalone_main();
  263.     else {
  264.         user_id = getuid();
  265.         group_id = getgid();
  266.         port = get_portnum(fileno(stdout),stdout);
  267.         process_request(0,stdout);
  268.     }
  269.  
  270. #else
  271.  
  272.   if (s == -1) {
  273.  #ifdef STANDALONE
  274.     struct sockaddr_in sin;
  275.  
  276.     while( ( s = serveraccept("http", &sin) ) != -1 )
  277.     {
  278.           fprintf(stderr, "Accepted a connection from %s, port %ld\n",
  279.           inet_ntoa(sin.sin_addr), sin.sin_port);
  280.  
  281.         port = get_portnum(s,s);
  282.         process_request(s,s);
  283.  
  284.     fclose( s );
  285.     } 
  286.  #endif
  287.       return 1;
  288.   }
  289.         port = get_portnum(s,s);
  290.         process_request(s,s);
  291. #endif
  292.  
  293. #ifndef AMITCP
  294.     fclose(stdin);
  295.     fclose(stdout);
  296. #endif
  297.     exit(0);
  298. }
  299.